<?php
namespace Service;

use think\Exception;
use service\LogService;

use Yansongda\Pay\Pay;

use app\common\model\User;
use app\common\model\UserSection;
use app\common\model\ProductOrder;
use app\common\model\ApplyInduction;

use app\api\controller\BaseController;

class PayService extends BaseController
{
    /**
     * 小程序创建订单
     */
    public static function createMiniProductOrder($order)
    {
        $config = self::getMiniConfig();
        return Pay::wechat($config)->mini($order);
    }

    /**
     * 小程序回调校验
     */
    public static function notifyCallback()
    {
        $pay = Pay::wechat(self::getMiniConfig());

        try{
            /** 验签 */
            $callbackData = $pay->callback();
            LogService::write(json_encode($callbackData));

            $orderNo = $callbackData['resource']['ciphertext']['out_trade_no'];

            $orderInfo = ProductOrder::getFind(['order_no' => $orderNo]);

            if(!$orderInfo) throw new Exception('小程序支付回调处理：订单不存在');
            if($orderInfo['pay_time'] > 0) throw new Exception('小程序支付回调处理：订单已经支付');

            $jobTime = User::getVal(['id' => $orderInfo['user_id']], 'job_time');
            if(!$jobTime) $jobTime = ApplyInduction::getVal(['user_id' => $orderInfo['user_id']], 'job_time');

            switch ($orderInfo['product_info']['pay_cycle']) {
                case 1:
                    $expireTime = strtotime("1 month", (int)$jobTime);
                    break;
                case 2:
                    $expireTime = strtotime("3 month", (int)$jobTime);
                    break;
                case 3:
                    $expireTime = strtotime("6 month", (int)$jobTime);
                    break;
                case 4:
                    $expireTime = strtotime("1 year", (int)$jobTime);
                    break;
            }

            self::beginTrans();

            /** 处理订单 */
            ProductOrder::edit(['id' => $orderInfo['id'], 'status' => 2, 'pay_time' => time(), 'expire_time' => $expireTime]);

            if(!UserSection::getVal(['id' => $orderInfo['section_id']], 'is_out')){
                /** 更新部门到期时间 */
                UserSection::edit(['id' => $orderInfo['section_id'], 'expire_time' => $expireTime]);
            }

            self::commitTrans();
        }catch(\Exception $e){
            self::rollbackTrans();
            LogService::write($e->getMessage());
        }
        
        return $pay->success();
    }

    /**
     * 获取小程序配置
     */
    public static function getMiniConfig()
    {
        return [
            'wechat' => [
                'default' => [
                    // 必填-商户号，服务商模式下为服务商商户号
                    'mch_id' => config('config.wechatpay_merchant_id'),
                    // 必填-商户秘钥
                    'mch_secret_key' => config('config.wechatpay_key'),
                    // 必填-商户私钥 字符串或路径
                    'mch_secret_cert' => app()->getRootPath() . 'cert/apiclient_key.pem',
                    // 必填-商户公钥证书路径
                    'mch_public_cert_path' => app()->getRootPath() . 'cert/apiclient_cert.pem',
                    // 必填
                    'notify_url' => config('config.mini_product_notify_url'),
                    // 选填-公众号 的 app_id
                    'mp_app_id' => '',
                    // 选填-小程序 的 app_id
                    'mini_app_id' => config('config.wechatpay_app_id'),
                    // 选填-app 的 app_id
                    'app_id' => '',
                    // 选填-合单 app_id
                    'combine_app_id' => '',
                    // 选填-合单商户号 
                    'combine_mch_id' => '',
                    // 选填-服务商模式下，子公众号 的 app_id
                    'sub_mp_app_id' => '',
                    // 选填-服务商模式下，子 app 的 app_id
                    'sub_app_id' => '',
                    // 选填-服务商模式下，子小程序 的 app_id
                    'sub_mini_app_id' => '',
                    // 选填-服务商模式下，子商户id
                    'sub_mch_id' => '',
                    // 选填-微信公钥证书路径, optional，强烈建议 php-fpm 模式下配置此参数
                    'wechat_public_cert_path' => [],
                    // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SERVICE
                    'mode' => Pay::MODE_NORMAL,
                ]
            ],
            'logger' => [ // optional
                'enable' => false,
                'file' => './logs/wechat.log',
                'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
                'type' => 'single', // optional, 可选 daily.
                'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
            ],
            'http' => [ // optional
                'timeout' => 5.0,
                'connect_timeout' => 5.0,
                // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
            ],
        ];
    }



    /**
     * 扫码支付创建订单
     */
    public static function createCodeProductOrder($order)
    {
        $config = self::getCodeConfig();
        return Pay::wechat($config)->scan($order);
    }

    /**
     * 扫码支付回调校验
     */
    public static function notifyCode()
    {
        $pay = Pay::wechat(self::getCodeConfig());

        try{
            /** 验签 */
            $callbackData = $pay->callback();

            $orderNo = $callbackData['resource']['ciphertext']['out_trade_no'];

            $orderInfo = ProductOrder::getFind(['order_no' => $orderNo]);

            if(!$orderInfo) throw new Exception('小程序支付回调处理：订单不存在');
            if($orderInfo['pay_time'] > 0) throw new Exception('小程序支付回调处理：订单已经支付');

            $userSectionInfo = UserSection::getFind(['id' => $orderInfo['section_id']], 'is_out, expire_time');
            if(!$userSectionInfo) $expireTime = User::getVal(['id' => $orderInfo['user_id']], 'job_time');

            if($userSectionInfo && $userSectionInfo['is_out'] == 1){
                $expireTime = ProductOrder::where(['user_id' => $orderInfo['user_id'], 'status' => 2])->order('id DESC')->value('expire_time');
            }

            switch ($orderInfo['product_info']['pay_cycle']) {
                case 1:
                    $expireTime = strtotime("1 month", (int)$expireTime);
                    break;
                case 2:
                    $expireTime = strtotime("3 month", (int)$expireTime);
                    break;
                case 3:
                    $expireTime = strtotime("6 month", (int)$expireTime);
                    break;
                case 4:
                    $expireTime = strtotime("1 year", (int)$expireTime);
                    break;
            }

            self::beginTrans();

            /** 处理订单 */
            ProductOrder::edit(['id' => $orderInfo['id'], 'status' => 2, 'pay_time' => time(), 'expire_time' => $expireTime]);

            if(!UserSection::getVal(['id' => $orderInfo['section_id']], 'is_out')){
                /** 更新部门到期时间 */
                UserSection::edit(['id' => $orderInfo['section_id'], 'expire_time' => $expireTime]);
            }

            self::commitTrans();
        }catch(\Exception $e){
            self::rollbackTrans();
            LogService::write($e->getMessage());
        }
        
        return $pay->success();
    }

    /**
     * 获取扫码支付配置
     */
    public static function getCodeConfig()
    {
        return [
            'wechat' => [
                'default' => [
                    // 必填-商户号，服务商模式下为服务商商户号
                    'mch_id' => config('config.wechatpay_merchant_id'),
                    // 必填-商户秘钥
                    'mch_secret_key' => config('config.wechatpay_key'),
                    // 必填-商户私钥 字符串或路径
                    'mch_secret_cert' => app()->getRootPath() . 'cert/apiclient_key.pem',
                    // 必填-商户公钥证书路径
                    'mch_public_cert_path' => app()->getRootPath() . 'cert/apiclient_cert.pem',
                    // 必填
                    'notify_url' => config('config.code_product_notify_url'),
                    // 选填-公众号 的 app_id
                    'mp_app_id' => config('config.wechatpay_app_id'),
                    // 选填-小程序 的 app_id
                    'mini_app_id' => '',
                    // 选填-app 的 app_id
                    'app_id' => '',
                    // 选填-合单 app_id
                    'combine_app_id' => '',
                    // 选填-合单商户号 
                    'combine_mch_id' => '',
                    // 选填-服务商模式下，子公众号 的 app_id
                    'sub_mp_app_id' => '',
                    // 选填-服务商模式下，子 app 的 app_id
                    'sub_app_id' => '',
                    // 选填-服务商模式下，子小程序 的 app_id
                    'sub_mini_app_id' => '',
                    // 选填-服务商模式下，子商户id
                    'sub_mch_id' => '',
                    // 选填-微信公钥证书路径, optional，强烈建议 php-fpm 模式下配置此参数
                    'wechat_public_cert_path' => [],
                    // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SERVICE
                    'mode' => Pay::MODE_NORMAL,
                ]
            ],
            'logger' => [ // optional
                'enable' => false,
                'file' => './logs/wechat.log',
                'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
                'type' => 'single', // optional, 可选 daily.
                'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
            ],
            'http' => [ // optional
                'timeout' => 5.0,
                'connect_timeout' => 5.0,
                // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
            ],
        ];
    }



    /**
     * 续费-扫码支付创建订单
     */
    public static function createRenewProductOrder($order)
    {
        $config = self::getRenewConfig();
        return Pay::wechat($config)->scan($order);
    }

    /**
     * 续费-扫码支付回调校验
     */
    public static function notifyRenew()
    {
        $pay = Pay::wechat(self::getRenewConfig());

        try{
            /** 验签 */
            $callbackData = $pay->callback();

            $orderNo = $callbackData['resource']['ciphertext']['out_trade_no'];

            $orderInfo = ProductOrder::getFind(['order_no' => $orderNo]);
            

            if(!$orderInfo) throw new Exception('小程序支付回调处理：订单不存在');
            if($orderInfo['pay_time'] > 0) throw new Exception('小程序支付回调处理：订单已经支付');

            $orderInfoAll = ProductOrder::getFind(['id' => $orderInfo['pid']]);

            $sectionInfo = UserSection::getFind(['id' => $orderInfo['section_id']], 'expire_time');

            switch ($orderInfo['product_info']['pay_cycle']) {
                case 1:
                    $expireTime = strtotime("1 month", $sectionInfo['expire_time']);
                    break;
                case 2:
                    $expireTime = strtotime("3 month", $sectionInfo['expire_time']);
                    break;
                case 3:
                    $expireTime = strtotime("6 month", $sectionInfo['expire_time']);
                    break;
                case 4:
                    $expireTime = strtotime("1 year", $sectionInfo['expire_time']);
                    break;
            }

            self::beginTrans();

            /** 处理订单 */
            ProductOrder::edit(['id' => $orderInfo['id'], 'status' => 2, 'pay_time' => time(), 'expire_time' => $expireTime]);

            if(!UserSection::getVal(['id' => $orderInfo['section_id']], 'is_out')){
                /** 更新部门到期时间 */
                UserSection::edit(['id' => $orderInfo['section_id'], 'expire_time' => $expireTime]);
            }

            /** 主订单的期数+1 */
            ProductOrder::setIncField(['id' => $orderInfo['pid']], 'installment_nums');

            /** 满期后主订单改为完成状态 */
            if($orderInfoAll['installment_nums'] + 1 >= $orderInfoAll['installment_nums_all']){
                ProductOrder::edit(['id' => $orderInfo['pid'], 'status' => 3, 'finish_time' => time()]);
            }

            self::commitTrans();
        }catch(\Exception $e){
            self::rollbackTrans();
            LogService::write($e->getMessage());
        }
        
        return $pay->success();
    }

    /**
     * 续费-获取扫码支付配置
     */
    public static function getRenewConfig()
    {
        return [
            'wechat' => [
                'default' => [
                    // 必填-商户号，服务商模式下为服务商商户号
                    'mch_id' => config('config.wechatpay_merchant_id'),
                    // 必填-商户秘钥
                    'mch_secret_key' => config('config.wechatpay_key'),
                    // 必填-商户私钥 字符串或路径
                    'mch_secret_cert' => app()->getRootPath() . 'cert/apiclient_key.pem',
                    // 必填-商户公钥证书路径
                    'mch_public_cert_path' => app()->getRootPath() . 'cert/apiclient_cert.pem',
                    // 必填
                    'notify_url' => config('config.renew_product_notify_url'),
                    // 选填-公众号 的 app_id
                    'mp_app_id' => config('config.wechatpay_app_id'),
                    // 选填-小程序 的 app_id
                    'mini_app_id' => '',
                    // 选填-app 的 app_id
                    'app_id' => '',
                    // 选填-合单 app_id
                    'combine_app_id' => '',
                    // 选填-合单商户号 
                    'combine_mch_id' => '',
                    // 选填-服务商模式下，子公众号 的 app_id
                    'sub_mp_app_id' => '',
                    // 选填-服务商模式下，子 app 的 app_id
                    'sub_app_id' => '',
                    // 选填-服务商模式下，子小程序 的 app_id
                    'sub_mini_app_id' => '',
                    // 选填-服务商模式下，子商户id
                    'sub_mch_id' => '',
                    // 选填-微信公钥证书路径, optional，强烈建议 php-fpm 模式下配置此参数
                    'wechat_public_cert_path' => [],
                    // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SERVICE
                    'mode' => Pay::MODE_NORMAL,
                ]
            ],
            'logger' => [ // optional
                'enable' => false,
                'file' => './logs/wechat.log',
                'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
                'type' => 'single', // optional, 可选 daily.
                'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
            ],
            'http' => [ // optional
                'timeout' => 5.0,
                'connect_timeout' => 5.0,
                // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
            ],
        ];
    }
}
